
#include <math.h>

#include "../../Command.h"

#include "../../Proxy.h"
#include "../../User.h"
#include "../../NLogic/Space.h"
#include "../../NLogic/Static.h"
#include "../../NLogic/SocialInfo.h"

namespace ProjectZ { namespace NCommand {

void SendFailPVPFriendMatch(User * pUser, int res)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(res);
	pAck->MakePacket(CMD_SC_PVP_FRIEND_MATCH_REQ);
	pUser->Send(pAck);
	return;
}

void Command::CS_PVP_FRIEND_MATCH_REQ(User * pUser, ::Network::Packet *pPacket)
{
/*	CS_PVP_FRIEND_MATCH_REQ			0x1314
	{
		u32	 u32gid;					/// 친구의 gid
		u8	 u8match_type;		/// 0:친선 대전, 1: 친구대전
	}

	SC_PVP_FRIEND_MATCH_REQ			0x1315
	{
		s16	ack;						/// 1:완료 ,  -1 실패
	}*/

	PREPARE_PACKET;

	int oppUserSeq	= 0;
	char matchType	= 0;	// 0:친선대전, 1:친구대전

	*pPacket >> oppUserSeq >> matchType;

	if (matchType < 0 || matchType > 1)
	{
		DEBUGLOG("CS_PVP_FRIEND_MATCH_REQ : Invalid Match type (%d)", matchType);
		return;
	}

	NLogic::Space * pSpace	= pUser->GetSpace();
	if (NULL == pSpace)
	{
		DEBUGLOG("CS_PVP_FRIEND_MATCH_REQ : pSpace is NULL!!");
		return;
	}

//	if (false == pUser->EndBattle_afterEffect())
//	{
//		SendFailPVPFriendMatch(pUser, ACK_BATTLE_AFTEREFFECT);
//		return;
//	}

	if (pUser->GetEnumState() != User::EnumState::__NONE__)
	{
		SendFailPVPFriendMatch(pUser, ACK_MATCHING_FAIL);
		DEBUGLOG("CS_PVP_FRIEND_MATCH_REQ : pUser->GetEnumState() != User::EnumState::__NONE__");
		return;
	}

	// 상대 검색
//	User * pOppUser = pSpace->FindUser(oppUserSeq);
	User * pOppUser = NProxy::GetUser(oppUserSeq);
	if (pOppUser == NULL)
	{
		SendFailPVPFriendMatch(pUser, ACK_MATCHING_FAIL);
		return;
	}

	if (pOppUser->GetEnumState() == User::EnumState::TUTORIAL)
	{
		SendFailPVPFriendMatch(pUser, ACK_MATCHING_FAIL);
		return;
	}

	if (NULL == pOppUser->GetSpace())
	{
		SendFailPVPFriendMatch(pUser, ACK_MATCHING_FAIL);
		return;
	}

	// 상대의 상태 및 위치를 확인
	if (pOppUser->GetEnumState() != User::EnumState::__NONE__
			&& pOppUser->GetSpace()->GetData()._spaceType != NLogic::Space::SpaceType::WORLD)
	{
		SendFailPVPFriendMatch(pUser, ACK_MATCHING_FAIL);
		return;
	}

	// 상대와의 레벨차이가 +10인 경우 대전 불가
	int levelGap = pUser->GetCharacterInfo().level - pOppUser->GetCharacterInfo().level;
	if (10 <= abs(levelGap))
	{
		SendFailPVPFriendMatch(pUser, ACK_MATCHING_LEVEL_GAP_OVERFLOW);
		return;
	}

	NLogic::SocialInfo * pSocialInfo = pOppUser->GetSocialInfo();
	if (NULL == pSocialInfo)
	{
		DEBUGLOG("CS_PVP_FRIEND_MATCH_REQ : pSocialInfo is NULL!!");
		return;
	}

	// 상대의 PVP 초대 여부가 OFF인 경우 매칭 실패
	if (!(pSocialInfo->GetData()->_invite_blocked & static_cast<int>(NLogic::SocialInfo::EnumInviteState::PVP_ON)))
	{
		SendFailPVPFriendMatch(pUser, ACK_MATCHING_FAIL);
		return;
	}

	// Party 생성
	NLogic::Party * pParty = NLogic::Static::Instance().GETPARTYPOOL()->NEW();
	pParty->Open(pUser);
	pParty->EnterUser(pOppUser);

	// PVP Space생성
	NLogic::Space::Data clsData;
	clsData._maxUser = 2;
	clsData._spaceType = NLogic::Space::SpaceType::PVP_USER;

	NLogic::Space * pPVPSpace = NLogic::Static::Instance().GETSPACEPOOL()->NEW();
	pPVPSpace->Open(pUser, clsData);
	pPVPSpace->SetParty(pParty);

	// 방장 입장
	pSpace->LeaveUser(pUser);
	pPVPSpace->EnterUser(pUser);

//	// 친선대전 여부 세팅
//	pPVPSpace->GetData()._bPVPAmity = true;

	// 응답
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << pUser->GetUserSeq();
	*pAck << matchType;
	*pAck << static_cast<int>(-1);		// 파티 Seq (사용안함)
	pAck->MakePacket(CMD_SC_PVP_MATCH_ASK);
	pOppUser->Send(pAck);

	// 대전 종류에 따라 유저의 상태 변경
	if (matchType == 0)
	{
		// 친선 대전
		pUser->SetEnumState(User::EnumState::PVP_AMITY_WAIT);
		pOppUser->SetEnumState(User::EnumState::PVP_AMITY_WAIT);
	}
	else if (matchType == 1)
	{
		// 친구 대전
		pUser->SetEnumState(User::EnumState::PVP_FRIENDLY_WAIT);
		pOppUser->SetEnumState(User::EnumState::PVP_FRIENDLY_WAIT);
	}

	// 파티 상태 변경
	pParty->SetState(NLogic::Party::State::PVP_ACCEPT_WAIT);
}

} /*NCommand*/ } /*ProjectZ*/
